Inline function

In various versions of the C and C++ programming languages, an inline function is a function upon which the compiler has been requested to perform inline expansion. In other words, the programmer has requested that the compiler insert the complete body of the function in every place that the function is called, rather than generating code to call the function in the one place it is defined. (However, compilers are not obligated to respect this request.)

Contents

Motivation

Inline expansion is used to eliminate the time overhead when a function is called. It is typically used for functions that execute frequently. It also has a space benefit for very small functions, and is an enabling transformation for other optimizations.

Without inline functions, however, the compiler decides which functions to inline. The programmer has little or no control over which functions are inlined and which are not. Giving this degree of control to the programmer allows for the use of application-specific knowledge in choosing which functions to inline.

Comparison with macros

Traditionally, in languages such as C, inline expansion was accomplished at the source level using parameterized macros. Use of true inline functions, as are available in C99, provides several benefits over this approach:

Many compilers can also inline expand some recursive functions; recursive macros are typically illegal.

Bjarne Stroustrup, the designer of C++, likes to emphasize that macros should be avoided wherever possible, and advocates extensive use of inline functions.

Language support

C++, C99, and GNU C each have support for inline functions. Different compilers vary in how complex a function they can manage to inline. Mainstream C++ compilers like Microsoft Visual C++ and GCC support an option that lets the compilers automatically inline any suitable function, even those not marked as inline functions.

An inline function can be written in C99 (see below for a problem in C99 regarding this definition) or C++ like this:

inline int max(int a, int b)
{
  return (a > b) ? a : b;
}

Then, a statement such as the following:

a = max(x, y);

may be transformed into a more direct computation:

a = (x > y) ? x : y;

Analogs in other languages

In the Ada programming language, there exists a pragma for inline functions. Most other languages, including Java and functional languages, do not provide language constructs for inline functions, but often do perform aggressive inline expansion.

Functions in Common Lisp may be defined as inline as such:[1]

 (declaim (inline dispatch))
 (defun dispatch (x)
   (funcall
     (get (car x) 'dispatch) x))

Microsoft Visual C++ specific

Microsoft Visual C++ and few other compilers support non-standard constructs for defining inline functions, such as __inline and __forceinline specifiers.

  1. The function or its caller is compiled with /Ob0 (the default option for debug builds).
  2. The function and the caller use different types of exception handling (C++ exception handling in one, structured exception handling in the other).
  3. The function has a variable argument list.
  4. The function uses inline assembly, unless compiled with /Og, /Ox, /O1, or /O2.
  5. The function is recursive and not accompanied by #pragma inline_recursion(on). With the pragma, recursive functions are inlined to a default depth of 16 calls. To reduce the inlining depth, use inline_depth pragma.
  6. The function is virtual and is called virtually. Direct calls to virtual functions can be inlined.
  7. The program takes the address of the function and the call is made via the pointer to the function. Direct calls to functions that have had their address taken can be inlined.
  8. The function is also marked with the naked __declspec modifier.

__forceinline is useful if:

Example of portable code:

#ifdef _MSC_VER
  #define INLINE __forceinline /* use __forceinline (VC++ specific) */
#else
  #define INLINE inline        /* use standard inline */
#endif
 
INLINE void helloworld() { /* function body */ }

Besides the problems associated with inline expansion in general, inline functions as a language feature may not be as valuable as they appear, for a number of reasons:

For problems with the optimization itself, rather than the language feature, see problems with inline expansion.

Quotes

"A function declaration [ . . . ] with an inline specifier declares an inline function. The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions defined by 7.1.2 shall still be respected."
— ISO 14882:1998(E), the current C++ standard, section 7.1.2
"A function declared with an inline function specifier is an inline function. [ . . . ] Making a function an inline function suggests that calls to the function be as fast as possible. The extent to which such suggestions are effective is implementation-defined (footnote: For example, an implementation might never perform inline substitution, or might only perform inline substitutions to calls in the scope of an inline declaration.)
"[ . . . ] An inline definition does not provide an external definition for the function, and does not forbid an external definition in another translation unit. An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition."
— ISO 9899:1999(E), the C99 standard, section 6.7.4

References

  1. ^ Declaration INLINE, NOTINLINE at the Common Lisp HyperSpec

See also

External links